#include "files/directory.h"

#include <dirent.h>

namespace Tvimeg
{
	Directory::Directory(void)
	{
	}

	Directory::Directory(const FilePath& pathIn)
		:	FileItem(pathIn)
	{
	}

	bool Directory::Exists(void) const
	{
		return FileItem::Exists(true);
	}

	std::string Directory::GetName(void) const
	{
		return GetNameAndExtension();
	}

	template<class Process>
	bool Directory::ScanDirectory(Process processor) const
	{
		DIR* directory = opendir(GetPath().c_str());
		if (directory)
		{
			dirent* entry = readdir(directory);
			while (entry)
			{
				std::string name(entry->d_name);
				if (name != "." && name != "..")
				{
					processor(*this + name, entry->d_type == DT_DIR);
				}

				entry = readdir(directory);
			}

			closedir(directory);
			return true;
		}
		else
		{
			return false;
		}
	}

	class DirectoryProcessor
	{
	public:
		DirectoryProcessor(Directory::DirectoryList& directories_in)
			:	directories(directories_in)
		{
		}

		void operator()(const FilePath& path, const bool is_directory)
		{
			if (is_directory)
			{
				directories.push_back(Directory(path));
			}
		}

	private:
		Directory::DirectoryList&	directories;
	};

	bool Directory::GetDirectories(DirectoryList& directories) const
	{
		DirectoryProcessor processor(directories);
		return ScanDirectory(processor);
	}

	class FileProcessor
	{
	public:
		FileProcessor(Directory::FileList& files_in)
			:	files(files_in)
		{
		}

		void operator()(const FilePath& path, const bool is_directory)
		{
			if (!is_directory)
			{
				files.push_back(File(path));
			}
		}

	private:
		Directory::FileList&	files;
	};

	bool Directory::GetFiles(FileList& files) const
	{
		FileProcessor processor(files);
		return ScanDirectory(processor);
	}

	File Directory::GetRelativeFile(const FilePath& path) const
	{
		return File(*this + path);
	}

	Directory Directory::GetRelativeDirectory(const FilePath& path) const
	{
		return Directory(*this + path);
	}
}
